package org.dromara.web.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.common.profile.Language;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.MediaInfo;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaRequest;
import com.tencentcloudapi.vod.v20180717.models.SearchMediaResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.domain.R;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.system.domain.vo.TrtcRecordTaskVo;
import org.dromara.system.service.ITrtcRecordTaskService;
import org.dromara.web.properties.TrtcProperties;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.Map;

/**
 * TRTC 录制回调控制器
 *
 * @author aaron
 */
@Slf4j
@SaIgnore
@RestController
@RequiredArgsConstructor
@RequestMapping("/trtc/callback/recording")
public class TrtcRecordingCallbackController {
    private final TrtcProperties trtcProperties;
    private final ITrtcRecordTaskService trtcRecordTaskService;

    /**
     * 处理录制事件回调
     *
     * @param body 回调数据
     * @return 处理结果
     */
    @PostMapping
    public R<Void> handleRecordingCallback(@RequestBody String body) {
        log.info("收到TRTC录制回调: {}", body);

        try {
            Map<String, Object> callbackData = JsonUtils.parseMap(body);

            // 打印回调数据的所有字段
            log.info("=== TRTC录制回调数据开始 ===");
            for (Map.Entry<String, Object> entry : callbackData.entrySet()) {
                if (entry.getValue() instanceof Map) {
                    log.info("字段名: {}, 值类型: Map", entry.getKey());
                    Map<String, Object> nestedMap = (Map<String, Object>) entry.getValue();
                    for (Map.Entry<String, Object> nestedEntry : nestedMap.entrySet()) {
                        log.info("  - 子字段名: {}, 子字段值: {}, 子字段类型: {}",
                            nestedEntry.getKey(),
                            nestedEntry.getValue(),
                            nestedEntry.getValue() != null ? nestedEntry.getValue().getClass().getSimpleName() : "null");
                    }
                } else {
                    log.info("字段名: {}, 字段值: {}, 值类型: {}",
                        entry.getKey(),
                        entry.getValue(),
                        entry.getValue() != null ? entry.getValue().getClass().getSimpleName() : "null");
                }
            }
            log.info("=== TRTC录制回调数据结束 ===");

            Integer eventType = (Integer) callbackData.get("EventType");
            Map<String, Object> eventInfo = (Map<String, Object>) callbackData.get("EventInfo");

            switch (eventType) {
                case 301:
                    handleRecordingStarted(eventInfo);
                    break;
                case 302:
                    handleRecordingExit(eventInfo);
                    break;
//                case "RecordingError":
//                    handleRecordingError(eventInfo);
//                    break;
                case 311:
                    handleRecordingFileUploaded(eventInfo);
                    break;
                case 312:
                    handleRecordingStopped(eventInfo);
                    break;
                default:
                    log.warn("未知的TRTC录制回调事件类型: {}", eventType);
            }

            return R.ok();
        } catch (Exception e) {
            log.error("处理TRTC录制回调失败", e);
            return R.fail("处理录制回调失败");
        }
    }

    /**
     * 处理录制开始事件
     */
    private void handleRecordingStarted(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        Object taskIdObj = eventInfo.get("TaskId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String taskId = taskIdObj != null ? taskIdObj.toString() : null;
        log.info("录制开始: roomId={}, taskId={}", roomId, taskId);
    }

    /**
     * 云端录制模块退出
     */
    private void handleRecordingExit(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        Object taskIdObj = eventInfo.get("TaskId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String taskId = taskIdObj != null ? taskIdObj.toString() : null;
        log.info("录制模块退出: roomId={}, taskId={}", roomId, taskId);
    }

    private void handleRecordingStopped(Map<String, Object> eventInfo) throws TencentCloudSDKException {
        Object roomIdObj = eventInfo.get("RoomId");
        Object taskIdObj = eventInfo.get("TaskId");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String taskId = taskIdObj != null ? taskIdObj.toString() : null;
        Credential cred = new Credential(trtcProperties.getSecretId(), trtcProperties.getSecretKey());
        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setReqMethod("GET"); // get请求(默认为post请求)
        httpProfile.setConnTimeout(30); // 请求连接超时时间，单位为秒(默认60秒)
        httpProfile.setWriteTimeout(30);  // 设置写入超时时间，单位为秒(默认0秒)
        httpProfile.setReadTimeout(30);  // 设置读取超时时间，单位为秒(默认0秒)
        httpProfile.setEndpoint("vod.tencentcloudapi.com"); // 指定接入地域域名(默认就近接入)
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setSignMethod(ClientProfile.SIGN_TC3_256); // 指定签名算法(默认为TC3-HMAC-SHA256)
        clientProfile.setHttpProfile(httpProfile);
        clientProfile.setDebug(true);
        clientProfile.setLanguage(Language.ZH_CN);
        VodClient vodClient = new VodClient(cred, "ap-shanghai", clientProfile);
        SearchMediaRequest searchMediaRequest = new SearchMediaRequest();
        searchMediaRequest.setSubAppId(trtcProperties.getSubAppId());
        Long[] trtcSdkAppIds = new Long[1];
        trtcSdkAppIds[0] = trtcProperties.getSdkAppId();
        searchMediaRequest.setTrtcSdkAppIds(trtcSdkAppIds);
        String[] trtcRoomIds = new String[1];
        trtcRoomIds[0] = roomId;
        searchMediaRequest.setTrtcRoomIds(trtcRoomIds);
        SearchMediaResponse searchMediaResponse = vodClient.SearchMedia(searchMediaRequest);
        MediaInfo[] mediaInfos = searchMediaResponse.getMediaInfoSet();
    }

    /**
     * 处理录制错误事件
     */
    private void handleRecordingError(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        Object taskIdObj = eventInfo.get("TaskId");
        Object errorCodeObj = eventInfo.get("ErrorCode");
        Object errorMessageObj = eventInfo.get("ErrorMessage");
        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String taskId = taskIdObj != null ? taskIdObj.toString() : null;
        String errorCode = errorCodeObj != null ? errorCodeObj.toString() : null;
        String errorMessage = errorMessageObj != null ? errorMessageObj.toString() : null;
        log.error("录制错误: roomId={}, taskId={}, errorCode={}, errorMessage={}",
            roomId, taskId, errorCode, errorMessage);
    }

    /**
     * 处理录制文件上传完成事件
     */
    private void handleRecordingFileUploaded(Map<String, Object> eventInfo) {
        Object roomIdObj = eventInfo.get("RoomId");
        Object taskIdObj = eventInfo.get("TaskId");
        Object fileNameObj = eventInfo.get("FileName");
        Object fileSizeObj = eventInfo.get("FileSize");
        Object fileUrlObj = eventInfo.get("FileUrl");
        Object startTimeObj = eventInfo.get("StartTime");
        Object endTimeObj = eventInfo.get("EndTime");
        Map<String, Object> payload = (Map<String, Object>) eventInfo.get("Payload");
        Map<String, Object> tencentVod = (Map<String, Object>) payload.get("TencentVod");
        Object fileIdObj = tencentVod.get("FileId");
        Object videoUrlObj = tencentVod.get("VideoUrl");

        String roomId = roomIdObj != null ? roomIdObj.toString() : null;
        String taskId = taskIdObj != null ? taskIdObj.toString() : null;
        String fileId = fileIdObj != null ? fileIdObj.toString() : null;
        String fileName = fileNameObj != null ? fileNameObj.toString() : null;
        String fileSize = fileSizeObj != null ? fileSizeObj.toString() : null;
        String fileUrl = fileUrlObj != null ? fileUrlObj.toString() : null;
        String startTime = startTimeObj != null ? startTimeObj.toString() : null;
        String endTime = endTimeObj != null ? endTimeObj.toString() : null;
        String videoUrl = videoUrlObj != null ? videoUrlObj.toString() : null;

        log.info("录制文件上传完成: roomId={}, taskId={}, fileId={}, fileName={}, fileSize={}, fileUrl={}, startTime={}, endTime={}",
            roomId, taskId, fileId, fileName, fileSize, fileUrl, startTime, endTime);
        TrtcRecordTaskVo trtcRecordTaskVo = trtcRecordTaskService.selectTaskInfoByRoomId(roomId);
        trtcRecordTaskVo.setRecordEndTime(new Date());
        trtcRecordTaskVo.setFileId(fileId);
        trtcRecordTaskVo.setVideoUrl(videoUrl);
        Long result = trtcRecordTaskService.updateTaskInfo(trtcRecordTaskVo);
        log.info("result: {}", result);
    }
}
